#include <pcap.h>
#include <iostream>
#include <string.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define SMTPS_PORT 465

using namespace std;

void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);

int main(int argc, char *argv[])
{
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *handle;

    // open network interface for capture
    handle = pcap_open_live("eno1", BUFSIZ, 1, 1000, errbuf);
    if (handle == NULL) {
        cerr << "Error opening network interface: " << errbuf << endl;
        exit(1);
    }

    // set filter for SMTPS traffic
    struct bpf_program fp;
    char filter_exp[] = "tcp port 465";
    if (pcap_compile(handle, &fp, filter_exp, 0, 0) == -1) {
        cerr << "Error compiling filter: " << pcap_geterr(handle) << endl;
        exit(1);
    }
    if (pcap_setfilter(handle, &fp) == -1) {
        cerr << "Error setting filter: " << pcap_geterr(handle) << endl;
        exit(1);
    }

    // start packet capture loop
    pcap_loop(handle, -1, packet_handler, NULL);

    // cleanup
    pcap_freecode(&fp);
    pcap_close(handle);
    return 0;
}

void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
    if (args) {
        std::cout << "======" << *args << std::endl;
    }

    // extract Ethernet header
    struct ether_header *eth_hdr;
    eth_hdr = (struct ether_header *)packet;
    // extract IP header
    struct iphdr *ip_hdr;
    ip_hdr = (struct iphdr *)(packet + sizeof(struct ether_header));
    // check if packet contains TCP data
    int tcp_hdr_len = sizeof(struct ether_header) + sizeof(struct iphdr) + sizeof(struct tcphdr);
    if ((header->caplen - tcp_hdr_len) <= 0) {
        return;
    }
    // extract TCP header
    struct tcphdr *tcp_hdr;
    tcp_hdr = (struct tcphdr *)(packet + sizeof(struct ether_header) + sizeof(struct iphdr));
    // check if destination port is SMTPS
    if (ntohs(tcp_hdr->dest) != SMTPS_PORT) {
        return;
    }
    // extract SSL data
    const u_char *ssl_data;
    ssl_data = packet + tcp_hdr_len;
    int ssl_data_len = header->caplen - tcp_hdr_len;

    // create SSL context and bio
    SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
    BIO *bio = BIO_new(BIO_s_mem());
    SSL *ssl = SSL_new(ctx);

    // write SSL data to bio
    int ddd = BIO_write(bio, ssl_data, ssl_data_len);

    // int dsds = SSL_set_fd(ssl, *(int *)args);
    // std::cout << "===ddd===" << dsds << std::endl;
    // connect SSL to bio
    SSL_set_bio(ssl, bio, bio);

    // read SSL record
    char buf[BUFSIZ];
    int leee = SSL_read(ssl, buf, BUFSIZ);
    // std::cout << "===10===" << leee << buf << std::endl;
    // parse email sender information from SSL data
    char *from_pos = strstr(buf, "From:");
    if (from_pos == NULL) {
        return;
    }

    char *from_start = from_pos + 5;
    char *from_end = strchr(from_start, '\r');
    if (from_end == NULL) {
        return;
    }

    int from_len = from_end - from_start;
    char from_email[from_len + 1];
    strncpy(from_email, from_start, from_len);
    from_email[from_len] = '\0';

    // output email sender information
    cout << "Email Sender: " << from_email << endl;

    // cleanup SSL resources
    SSL_free(ssl);
    SSL_CTX_free(ctx);
}
